package com.label.Service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import com.label.Dao.*;
import com.label.Model.Do.*;
import com.label.Model.Query.TaskDetailQuery;
import com.label.Model.Query.TaskQuery;
import com.label.Model.Query.TaskQuestionQuery;
import com.label.Model.Query.TemplateQuery;
import com.label.Model.Vo.TaskVo;
import com.label.Model.Vo.TemplateVo;
import com.label.Service.TaskService;
import com.label.Utils.Common.InfoUtil;
import com.label.Utils.UserUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = {Exception.class})
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private TaskDetailMapper taskDetailMapper;

    @Resource
    private TaskQuestionMapper taskQuestionMapper;

    @Resource
    private MessageInfoMapper messageInfoMapper;

    @Resource
    private MessageMapper messageMapper;

    @Resource
    private TemplateMapper templateMapper;


    @Autowired
    @Qualifier("oracleJdbcTemplate")
    private JdbcTemplate oracleJdbc;

    @Override
    public Boolean addTask(TaskQuery taskQuery) {
        Task task=BeanUtil.copyProperties(taskQuery,Task.class);

        User own=UserUtil.getUser();
        task.setSenderId(own.getAccount());
        task.setSenderName(own.getUserName());
        task.setCount(0);
        taskMapper.insert(task);

        MessageInfo messageInfo=new MessageInfo(task.getTitle(),task.getSenderName()+"给您发了一个新的通知，请及时查看。");
        messageInfoMapper.insert(messageInfo);

        List<Map<String,Object>> templateGroup=(List<Map<String,Object>>)JSONObject.parse(taskQuery.getReceiverList().get("groupList").toString());
        int stuCount=0;

        //循环几个模板
        for(Map<String,Object> templateMap:templateGroup){
            Template template=templateMapper.selectById(templateMap.get("classExample").toString());

            //通知班长
            User monitor=userMapper.getOneUserByAccount(template.getMonitor());
            TaskDetail taskDetailMonitor=new TaskDetail(task.getTaskId(),monitor.getAccount(),monitor.getUserName(),monitor.getAccount(),"2",template.getClassId());
            taskDetailMapper.insert(taskDetailMonitor);
            Message messageMonitor=new Message(task.getSenderId(),monitor.getAccount(),0,task.getSenderName(),monitor.getUserName(),messageInfo.getMessageInfoId().toString());
            messageMapper.insert(messageMonitor);
            stuCount++;

            //小组的map
            Map<String,Object> group=(Map<String,Object>)JSONObject.parse(template.getContent());
            List<Map<String,Object>> userGroups= (List<Map<String, Object>>) Convert.toList(group.get("groupList"));
            for(Map<String,Object> userGroup:userGroups){
                List<String> userIds=Convert.toList(String.class,userGroup.get("groupStu"));
                List<User> users=userMapper.selectList(new QueryWrapper<User>().lambda().in(User::getAccount,userIds));


                for(User user:users){
                    TaskDetail taskDetail=new TaskDetail(task.getTaskId(),user.getAccount(),user.getUserName(),userGroup.get("groupLeader").toString(), userGroup.get("groupLeader").equals(user.getAccount())?"1":"0",template.getClassId());
                    taskDetailMapper.insert(taskDetail);
                    stuCount++;
                    //通知所有学生
                    Message message=new Message(task.getSenderId(),user.getAccount(),0,task.getSenderName(),user.getUserName(),messageInfo.getMessageInfoId().toString());
                    messageMapper.insert(message);
                }
            }
        }

        Task  task1=new Task();
        task1.setTaskId(task.getTaskId());
        task1.setCount(stuCount);
        taskMapper.updateById(task1);

        return true;
    }

    @Override
    public List<TaskVo> getAllTeacherTask(){
        User own=UserUtil.getUser();
        List<Task> tasks=taskMapper.getAllTaskBySender(own.getAccount());
        return toVo(tasks);
    }

    @Override
    public List<TaskVo> getAllStuTask(){
        User own=UserUtil.getUser();
        List<Task> tasks=taskMapper.getAllStuTaskByRes(own.getAccount());
        tasks.addAll(taskMapper.getAllMonitorTaskByRes(own.getAccount()));
        return toVo(tasks);
    }

    @Override
    public Boolean updateState(TaskDetailQuery taskDetailQuery){
        TaskDetail taskDetail=BeanUtil.copyProperties(taskDetailQuery,TaskDetail.class);
        taskDetail.setDetailState(1);
        taskDetailMapper.updateById(taskDetail);
        return true;
    }

    @Override
    public Boolean addQuestion(TaskQuestionQuery taskQuestionQuery){
        TaskQuestion taskQuestion=BeanUtil.copyProperties(taskQuestionQuery,TaskQuestion.class);
        TaskDetail taskDetail=new TaskDetail(taskQuestion.getDetailId(),2);
        taskDetailMapper.updateById(taskDetail);
        taskQuestionMapper.insert(taskQuestion);
        return true;
    }

    @Override
    public Boolean answerQuestion(TaskQuestionQuery taskQuestionQuery){
        taskQuestionMapper.updateById(taskQuestionQuery.getAnswer(),taskQuestionQuery.getQuestionId());

        TaskQuestion taskQuestion=taskQuestionMapper.selectById(taskQuestionQuery.getQuestionId());

        Task task=taskMapper.selectById(taskQuestion.getTaskId());
        MessageInfo messageInfo=new MessageInfo(task.getTitle()+"问题做答","您在"+task.getTitle()+"中提出的问题，老师已做出回答，请及时查看。");
        messageInfoMapper.insert(messageInfo);

        User user=UserUtil.getUser();
        TaskDetail taskDetail=taskDetailMapper.selectById(taskQuestion.getDetailId());
        Message message=new Message(user.getId().toString(),taskDetail.getReceiverId(),0,user.getUserName(),taskDetail.getReceiverName(),messageInfo.getMessageInfoId().toString());
        messageMapper.insert(message);

        return true;
    }

    @Override
    public Boolean delQuestion(TaskQuestionQuery taskQuestionQuery) {
        User user=UserUtil.getUser();
        TaskQuestion taskQuestion=taskQuestionMapper.selectById(taskQuestionQuery.getQuestionId());
        TaskDetail taskDetail=taskDetailMapper.selectById(taskQuestion.getDetailId());
        if(!user.getAccount().equals(taskDetail.getReceiverId())||taskQuestion.getStates()==1)
            return false;
        taskQuestionMapper.deleteById(taskQuestionQuery.getQuestionId());
        return true;
    }

    @Override
    public Boolean updateQuestion(TaskQuestionQuery taskQuestionQuery) {//若已回答则并不能进行修改问题
        User user=UserUtil.getUser();
        TaskQuestion taskQuestion=taskQuestionMapper.selectById(taskQuestionQuery.getQuestionId());
        TaskDetail taskDetail=taskDetailMapper.selectById(taskQuestion.getDetailId());
        if(!user.getAccount().equals(taskDetail.getReceiverId())||taskQuestion.getStates()==1)
            return false;
        TaskQuestion taskQuestion1=new TaskQuestion();
        taskQuestion1.setQuestionId(taskQuestionQuery.getQuestionId());
        taskQuestion1.setAnswer(taskQuestionQuery.getContent());
        taskQuestionMapper.updateById(taskQuestion1);
        return true;
    }

    @Override
    public Boolean delTask(TaskQuery taskQuery) {
        User user=UserUtil.getUser();
        Task task=taskMapper.selectById(taskQuery.getTaskId());
        if(!user.getAccount().equals(task.getSenderId()))
            return false;
        //删除task，detail，question
        taskMapper.deleteById(taskQuery.getTaskId());
        taskQuestionMapper.delete(new QueryWrapper<TaskQuestion>().lambda().eq(TaskQuestion::getTaskId,taskQuery.getTaskId()));
        taskDetailMapper.delete(new QueryWrapper<TaskDetail>().lambda().eq(TaskDetail::getTaskId,taskQuery.getTaskId()));
        return true;
    }

    @Override
    public Boolean updateTask(TaskQuery taskQuery) {//更新标题，内容或者通知人
        User user=UserUtil.getUser();
        Task task=taskMapper.selectById(taskQuery.getTaskId());
        if(!user.getAccount().equals(task.getSenderId()))
            return false;

        Task task1=new Task();
        if(taskQuery.getTitle()!=null)
            task1.setTitle(taskQuery.getTitle());
        if(taskQuery.getContent()!=null)
            task1.setContent(taskQuery.getContent());
        taskMapper.updateById(task1);

        //更改通知状态为未读。
        TaskDetail taskDetail=new TaskDetail();
        taskDetail.setDetailState(0);
        taskDetailMapper.update(taskDetail,new UpdateWrapper<TaskDetail>().lambda().eq(TaskDetail::getTaskId,task.getTaskId()));

        return true;
    }

    @Override
    public List<Map<String,Object>> getStuUsers(){
        List<Map<String,Object>> users=oracleJdbc.queryForList("select * from (select * from sysuser where class_id is not null) u left join (select id,CLASS_NAME from class) c on u.class_id=c.id");
        Map<String, List<Map<String,Object>>> userGroup = users.stream().collect(Collectors.groupingBy(p->p.get("class_id").toString()));

        List<Map<String,Object>> res=new ArrayList<>();
        userGroup.forEach((k,v)->{
            List<Map<String,Object>> resUser=v.stream().map(p-> ImmutableMap.of("title",p.get("USERNAME"),"value",p.get("ACCOUNT"),"key",p.get("ACCOUNT"))).collect(Collectors.toList());
            Map<String,Object> part=new HashMap<>();
            part.put("title",v.get(0).get("CLASS_NAME"));
            part.put("value",v.get(0).get("CLASS_ID"));
            part.put("key",v.get(0).get("CLASS_ID"));
            part.put("children",resUser);
            res.add(part);
        });
        return res;
    }

    public Boolean sendTeacher(TaskQuery taskQuery){
        Task task=taskMapper.selectById(taskQuery.getTaskId());
        User user=UserUtil.getUser();

        MessageInfo messageInfo=new MessageInfo("< "+task.getTitle()+"> 通知进度",InfoUtil.getClassName(user.getClassId())+"班内全员阅读并确认 <"+task.getTitle()+"> 通知，请您及时查阅！");
        messageInfoMapper.insert(messageInfo);
        Message message=new Message(user.getAccount(),task.getSenderId(),0,user.getUserName(),task.getSenderName(),messageInfo.getMessageInfoId().toString());
        messageMapper.insert(message);

        return true;
    }

    public List<Map<String,Object>> getAllClassAndTemplate(){
        List<Map<String,Object>> classes=oracleJdbc.queryForList("select * from (select class_id from sysuser where class_id is not null group by class_id) u left join (select id,CLASS_NAME from class) c on u.class_id=c.id");
        List<Map<String,Object>> templates=oracleJdbc.queryForList("select template_id,template_class,template_name from template");

        List<Map<String,Object>> res=new ArrayList<>();

        classes.forEach(v->{
            List<Map<String,Object>> resTemplate=templates.stream().filter(p->p.get("TEMPLATE_CLASS").equals(v.get("CLASS_ID").toString())).collect(Collectors.toList());
            Map<String,Object> part=new HashMap<>();
            part.put("classname",v.get("CLASS_NAME"));
            part.put("classid",v.get("CLASS_ID"));
            part.put("example",resTemplate);
            res.add(part);
        });
        return res;
    }

    public TemplateVo getOneTemplate(TemplateQuery templateQuery){
        return templateToVo(templateMapper.selectById(templateQuery.getTemplateId()));
    }

    public Boolean addTemplate(TemplateQuery templateQuery){
        Template template=new Template(templateQuery.getExampleName(),templateQuery.getClassid(), JSONObject.toJSONString(templateQuery),UserUtil.getUser().getAccount(),templateQuery.getMonitor());
        templateMapper.insert(template);
        return true;
    }

    public Boolean updateTemplate(TemplateQuery templateQuery){
        Template template=new Template(templateQuery.getExampleName(),templateQuery.getClassid(), JSONObject.toJSONString(templateQuery),UserUtil.getUser().getAccount(),templateQuery.getMonitor());
        template.setTemplateId(templateQuery.getTemplateId());
        templateMapper.updateById(template);
        return true;
    }

    private TemplateVo templateToVo(Template template){
        TemplateVo templateVo=BeanUtil.copyProperties(template,TemplateVo.class);
        templateVo.setClassName(InfoUtil.getClassName(templateVo.getClassId()));
        return templateVo;
    }

    private List<TaskVo> toVo(List<Task> tasks){
        List<TaskVo> taskVos=new ArrayList<TaskVo>();
        for(Task task:tasks){
            TaskVo taskVo=JSONObject.parseObject(JSON.toJSONString(task),TaskVo.class);

            Map<String,List<TaskDetail>> classGroup=task.getTaskDetails().stream().collect(Collectors.groupingBy(TaskDetail::getDetailClass));
            TreeMap<String,List<TaskDetail>> sortClassGroup=new TreeMap<>(classGroup);

            List<Map<String,Object>> res=new ArrayList<>();
            sortClassGroup.forEach((k,v)->{   //班级的list，K是班级id，v是班级的人。
                Map<String,Object> resClass= new HashMap<>();
                resClass.put("class",InfoUtil.getClassName(k));

                List<Map<String,Object>> teamContent=new ArrayList<>();

                Map<String,List<TaskDetail>> teamGroup=v.stream().collect(Collectors.groupingBy(TaskDetail::getCharger));
                TreeMap<String,List<TaskDetail>> sortTeamGroup=new TreeMap<>(teamGroup);
                sortTeamGroup.forEach((m,n)->{ //分组，m为组长或班长id
                    Map<String,Object> resTeam= new HashMap<>();

                    List<Map<String,String>> resTeamContent=new ArrayList<>();
                    n.forEach(p->{

                        if(!p.getLeader().equals("0")){
                            if(p.getLeader().equals("1"))
                                resTeam.put("name",p.getReceiverName()+"组");
                            else
                                resTeam.put("name","班长");
                        }

                        Map<String,String> group = new HashMap<>();
                        User user=userMapper.getOneUserByAccount(p.getReceiverId());

                        if(user.getAccount().equals(UserUtil.getUser().getAccount())) {
                            taskVo.setLeaderFlag(p.getLeader());
                            taskVo.setStuState(p.getDetailState());
                            taskVo.setStuDetailId(p.getDetailId());
                        }


                        group.put("userId",p.getReceiverId());
                        group.put("name",p.getReceiverName());
                        group.put("phone",user.getPhone()!=null?user.getPhone():"无");
                        group.put("email",user.getEmail()!=null?user.getEmail():"无");
                        group.put("class", InfoUtil.getClassName(user.getClassId()));
                        group.put("charger", p.getLeader());
                        group.put("state",p.getDetailState().toString());

                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        group.put("createTime",sdf.format(p.getCreateTime()));
                        group.put("updateTime",sdf.format(p.getUpdateTime()));

                        resTeamContent.add(group);
                    });

                    resTeam.put("content",resTeamContent);
                    teamContent.add(resTeam);
                });
                teamContent.sort((o1, o2) -> {
                    if (o1.get("name").equals("班长"))
                        return -1;
                    if (o2.get("name").equals("班长"))
                        return 1;
                    return StringUtils.compare(o1.get("name").toString(),o2.get("name").toString());
                });
                resClass.put("content",teamContent);
                res.add(resClass);
            });
            taskVo.setTotalCount(task.getTaskDetails().size());
            taskVo.setConfirmCount(Math.toIntExact(task.getTaskDetails().stream().filter(p -> p.getDetailState() == 1).count()));
            taskVo.setTaskDetailGroups(res);
            taskVo.setTaskQuestions(taskQuestionMapper.getAllQuestionByTask(task.getTaskId()));
            taskVos.add(taskVo);
        }
        return taskVos;
    }

}
